package com.hcc.flow.server.service.sys;

import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Calendar;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.hcc.flow.server.common.model.ApiResult;
import com.hcc.flow.server.common.utils.FileUtil;
import com.hcc.flow.server.common.vo.FileVO;

import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.MultimediaInfo;

@Service
public class FileService {

	private static final Logger log = LoggerFactory.getLogger("adminLogger");

	@Value("${files.path}")
	private String filesPath;
	@Value("${files.path-linux}")
	private String filesPathLinux;
	@Value("${files.support-format}")
	private String SUPPORT_FORMAT;

	public ApiResult<?> save(MultipartFile file, HttpServletResponse response, HttpServletRequest request)
			throws IOException {
		String filesPathNow;
		String os = System.getProperty("os.name");
		if (os.toLowerCase().startsWith("win")) {
			filesPathNow = filesPath;
		} else {
			filesPathNow = filesPathLinux;
		}
		String fileOrigName = file.getOriginalFilename();
		if (!fileOrigName.contains(".")) {
			return ApiResult.error("缺少后缀名");
		}
		String fileFormat = fileOrigName.substring(fileOrigName.lastIndexOf(".") + 1);
		log.info("==============file type ：" + fileFormat + " \n");
		boolean isDo = FileUtil.isRightFormatFile(fileFormat, SUPPORT_FORMAT);
		if (!isDo) {
			log.error("==============file type：" + fileFormat + " not allow upload\n");
			return ApiResult.error("该文件格式." + fileFormat + "不允许上传");
		}
		Calendar date = Calendar.getInstance();
		String fileAddr = File.separator + date.get(Calendar.YEAR) + File.separator + (date.get(Calendar.MONTH) + 1)
				+ File.separator + date.get(Calendar.DAY_OF_MONTH);
		String filePath = filesPathNow + fileAddr;
		String md5 = FileUtil.fileMd5(file.getInputStream());
		fileOrigName = fileOrigName.substring(fileOrigName.lastIndexOf("."));
		// String pathname = FileUtil.getPath() + md5 + fileOrigName;
		String fileName = getFilename(file.getOriginalFilename(), md5);
		// String fullPath = filesPathNow + pathname;
		String fullPath = filePath + File.separator + fileName;
		FileUtil.saveFile(file, fullPath);
		long size = file.getSize();
		if ((size / 2024) > 51200) {
			return ApiResult.error("超过50M的文件不允许上传");
		}
		String contentType = file.getContentType();
		FileVO fileInfo = new FileVO();
		fileInfo.setMd5(md5);
		fileInfo.setContentType(contentType);
		fileInfo.setSize(size);
		fileInfo.setPath(fullPath);
		fileInfo.setUrl(fileAddr + File.separator + fileName);
		fileInfo.setName(file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf(".")));
		int fileType = GetFileType(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")));
		fileInfo.setType(fileType);
		if (fileType == 1) {
			fileInfo.setSecond(0L);// 默认10s
			GetImageRatio(file.getInputStream(), fileInfo);
		} else if (fileType == 2) {
			GetVideoRatio(fullPath, fileInfo);
		} else {
			fileInfo.setSecond(0L);// 默认10s
		}
		log.debug("上传文件{}", fullPath);
		return ApiResult.data(fileInfo);
	}

	public String downloadFile(String url, HttpServletResponse response) {
		String filesPathNow;
		String strRes = null;
		try {
			if (url != null) {
				String strName = url.substring(url.lastIndexOf("/") + 1);
				String newPath = "";
				String yos = System.getProperty("os.name");
				if (yos.toLowerCase().startsWith("win")) {
					newPath = url.replace("/", "\\");// windows
					filesPathNow = filesPath;
				} else {
					newPath = url;// linux系统时
					filesPathNow = filesPathLinux;
				}
				String fileName = strName;// 设置文件名，根据业务需要替换成要下载的文件名
				String realPath = filesPathNow + newPath;
				if (fileName != null) {
					// logger.info("========downed file：" + newPath );
					// 设置文件路径
					File file = new File(realPath);
					if (file.exists()) {
						response.setContentType("application/force-download");// 设置强制下载不打开
						response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 设置文件名
						byte[] buffer = new byte[1024];
						FileInputStream fis = null;
						BufferedInputStream bis = null;
						try {
							fis = new FileInputStream(file);
							bis = new BufferedInputStream(fis);
							OutputStream os = response.getOutputStream();
							int i = bis.read(buffer);
							while (i != -1) {
								os.write(buffer, 0, i);
								i = bis.read(buffer);
							}
							log.info("下载文件：" + url);

						} catch (Exception e) {
							e.printStackTrace();
							strRes = e.getMessage();
						} finally {
							if (bis != null) {
								try {
									bis.close();
								} catch (IOException e) {
									e.printStackTrace();
									strRes = e.getMessage();
								}
							}
							if (fis != null) {
								try {
									fis.close();
								} catch (IOException e) {
									e.printStackTrace();
									strRes = e.getMessage();
								}
							}
						}
					}
				} else {
					log.error("========downed file：" + newPath + " not exist!");
				}
			}
		} catch (Exception ex) {
			strRes = ex.getMessage();
			log.error("========downed file error:" + ex.getMessage());
		}
		return strRes;
	}

	/**
	 * 生成文件名
	 * 
	 * @param originalFilename
	 *            原名称
	 * @return string
	 */
	private String getFilename(String originalFilename, String md5) {
		String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
		String filename = new StringBuffer().append(md5).append(suffix).toString();
		return filename;
	}

	/**
	 * 获取文件类型 1视频2图片4文档5压缩文件6其他
	 * 
	 * @param contentType
	 * @return
	 */
	private int GetFileType(String contentType) {
		int type = 6;
		String strType = contentType.substring(contentType.lastIndexOf(".") + 1);
		// 图片
		if ("JPG".equalsIgnoreCase(strType) || "PNG".equalsIgnoreCase(strType) || "JPEG".equalsIgnoreCase(strType)
				|| "JPG".equalsIgnoreCase(strType) || "GIF".equalsIgnoreCase(strType)
				|| "BMP".equalsIgnoreCase(strType)) {
			type = 1;
		}
		// 视频
		else if ("AVI".equalsIgnoreCase(strType) || "MP4".equalsIgnoreCase(strType) || "FLV".equalsIgnoreCase(strType)
				|| "MOV".equalsIgnoreCase(strType) || "WMV".equalsIgnoreCase(strType)
				|| "MPEG".equalsIgnoreCase(strType) || "RMVB".equalsIgnoreCase(strType)
				|| "RM".equalsIgnoreCase(strType) || "VOB".equalsIgnoreCase(strType)) {
			type = 2;
		} else if ("TXT".equalsIgnoreCase(strType) || "DOC".equalsIgnoreCase(strType)
				|| "DOCX".equalsIgnoreCase(strType) || "XLS".equalsIgnoreCase(strType)
				|| "XLSX".equalsIgnoreCase(strType) || "PDF".equalsIgnoreCase(strType)) {
			type = 4;
		} else if ("RAR".equalsIgnoreCase(strType) || "ZIP".equalsIgnoreCase(strType)
				|| "7Z".equalsIgnoreCase(strType)) {
			type = 5;
		}
		return type;
	}

	/**
	 * 获取图片的分辨率
	 * 
	 * @param fileAddr
	 *            文件所在的实际地址
	 * @return width*height
	 */
	public void GetImageRatio(InputStream inputStream, FileVO fileRes) {
		BufferedImage bi = null;
		try {
			bi = ImageIO.read(inputStream);
			int width = bi.getWidth();
			int height = bi.getHeight();
			String strRatio = String.valueOf(width) + "*" + String.valueOf(height);
			fileRes.setResolution(strRatio);
		} catch (IOException e) {
			e.printStackTrace();
			log.error("分析图文件失败：" + e.getMessage());
		}
	}

	/**
	 * 获取视频的分辨率 时长
	 * 
	 * @param fileAddr
	 *            文件所在的实际地址
	 * @return width*height
	 */
	public void GetVideoRatio(String fileAddr, FileVO fileRes) {

		File source = new File(fileAddr);
		try {
			Encoder encoder = new Encoder();
			MultimediaInfo m = encoder.getInfo(source);
			fileRes.setSecond(m.getDuration() / 1000);
			String strRatio = String.valueOf(m.getVideo().getSize().getWidth()) + "*"
					+ String.valueOf(m.getVideo().getSize().getHeight());
			fileRes.setResolution(strRatio);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("分析视频文件<" + fileAddr + ">失败：" + e.getMessage());
		}
	}
}
